
#include "display.h"

Display::Display( void ) {
  return;
}

Display::~Display( void ) {

}

const char* Display::getColor( const char& code ) { // public static
  switch ( code ) {
    case 'r': return "\033[0;31m";    // dark red
    case 'R': return "\033[0;31;1m";  // bright red
    case 'g': return "\033[0;32m";    // dark green
    case 'G': return "\033[0;32;1m";  // bright green
    case 'y': return "\033[0;33m";    // dark yellow
    case 'Y': return "\033[0;33;1m";  // bright yellow
    case 'b': return "\033[0;34m";    // dark blue
    case 'B': return "\033[0;34;1m";  // bright blue
    case 'm': return "\033[0;35m";    // dark magenta
    case 'M': return "\033[0;35;1m";  // bright magenta
    case 'c': return "\033[0;36m";    // dark cyan
    case 'C': return "\033[0;36;1m";  // bright cyan
    case 'w': return "\033[0;30m";    // dark gray
    case 'W': return "\033[0;37;1m";  // pure white
    case '{': return "{";             // bracket
    case '?':
      switch ( rand() % 14 ) {
        case  0: return "\033[0;31m";    // dark red
        case  1: return "\033[0;31;1m";  // bright red
        case  2: return "\033[0;32m";    // dark green
        case  3: return "\033[0;32;1m";  // bright green
        case  4: return "\033[0;33m";    // dark yellow
        case  5: return "\033[0;33;1m";  // bright yellow
        case  6: return "\033[0;34m";    // dark blue
        case  7: return "\033[0;34;1m";  // bright blue
        case  8: return "\033[0;35m";    // dark magenta
        case  9: return "\033[0;35;1m";  // bright magenta
        case 10: return "\033[0;36m";    // dark cyan
        case 11: return "\033[0;36;1m";  // bright cyan
        case 12: return "\033[0;30m";    // dark gray
        case 13: return "\033[0;37;1m";  // pure white
        default: return "\033[0;0;0m";   // default
      }
    default:  return "\033[0;0;0m";   // default
  }
}

std::string Display::parseColors( const std::string& src, char def ) { // public static
  std::string dest;
  register char c = 0;

  // Parse colors...
  for ( std::string::const_iterator it = src.begin(); it != src.end(); ++it ) {
    c = *it;
    if ( c == '{' ) {
      dest.append( Display::getColor( *(it+1) ) );
      ++it;
    } else {
      dest.append( 1, c );
    }
  }
  dest.append( Display::getColor( def ) );

  return dest;
}

std::string Display::formatColumns( const unsigned long& columns, const std::vector<std::string>& items, unsigned long width ) { // public static
  unsigned long rows = items.size()/columns+1;
  unsigned long column_width = width/columns;
  unsigned long offset = 0;
  unsigned long size = items.size();
  char* buffer = (char*)calloc( column_width, sizeof(char) );
  char* format = (char*)calloc( 16, sizeof(char) );
  std::string foo;
  std::string dest;

  // Create the format string to be used for output...
  sprintf( format, "%%-%lus", column_width );

  // Loop through rows and columns and print each item in the list...
  for ( unsigned long row = 0; row < rows; ++row ) {
    for ( unsigned long column = 0; column < columns; ++column ) {
      // Calculate our list offset for the current row/column...
      offset = column*rows+row;
      if ( offset < size ) {
        // The offset is a valid list element...
        foo = items[offset];
      } else {
        // The offset is out of bounds (only happens in rightmost column)...
        foo.clear();
      }
      // Copy the data...
      sprintf( buffer, format, foo.substr( 0, column_width ).c_str() );
      dest.append( buffer );
    }
    // Newline after every row but the last...
    if ( row < rows-1 ) {
      dest.append( 1, '\n' );
    }
  }

  free( buffer );
  free( format );
  return dest;
}

std::string Display::refactor( const std::vector<std::string>& v ) { // public static
  std::string s;
  char buffer[128];
  for ( std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it ) {
    sprintf( buffer, "%s\n", it->c_str() );
    s.append( buffer );
  }
  return s;
}

std::vector<std::string> Display::refactor( const std::string& s ) { // public static
  return Regex::explode( "\n", Regex::trim(s) );
}

